第五章 终端
在学习本章节的时候,我遇到了一些困难,主要是因为 CentOS7 没有默认安装 curses 开发包和 term 开发包(集成进 curses )。
因此需要:
-
安装开发包:
yum install ncurses-devel.x86_64
-
编译时加入 -lncurses 选项
对终端进行读写
标准模式和非标准模式
默认情况下,只有用户按下回车键后,程序才能读到终端的输入。这方便了使用删除键来纠正输入错误,用户觉得输入满意后,才按下回车传递数据给程序。
这种方式被称为标准模式。所有输入都基于行进行处理,在一个输入行完成前,终端接口负责管理所有键盘输入,应用程序读不到用户输入的任何字符。
还有一种模式是非标准模式,应用程序对用户输入字符的处理拥有更大的控制权。
除此之外,终端能够把中断字符转换为对应的新号(发送给程序)。
处理重定向输出
Linux 程序经常会把它们的输入或输出重定向到文件或其他程序。但有时候我们并不想这样做,比如一个菜单程序,没有必要把菜单的打印重定向。
可以使用 isatty 函数来检查标准输出是否被重定向了。它判断的是某一个文件描述符是否连接到了一个终端。
与终端进行对话
可以直接对终端进行读写,而不是通过标准输入输出。方法是使用特殊设备/dev/tty
。该设备始终指向当前终端或当前的登录会话。 Linux 把一切事物都看作文件,所以可以用一般文件的操作方式来对 /dev/tty
进行读写。
终端驱动程序和通用终端接口
Linux 提供了一组编程接口来控制终端驱动程序的行为。
下面是能够控制的主要功能:
-
行编辑:是否允许用退格键进行编辑。
-
缓存:是立即读取字符,还是等待一段可配置的延迟之后再读取它们。
-
回显:允许控制字符的回显,例如读取密码时。
-
回车/换行(CR/LF):定义如何在输入/输出时映射回车/换行符。
-
线速:很少用于PC控制台,但对调制解调器或通过串行线连接的终端就很重要。
termios 结构
termios 是在 POSIX 规范中定义的标准接口,通过设置 termios 类型的数据结构中的值和使用一小组函数调用,你就可以对终端接口进行控制。它们都定义在头文件 termios.h 中。
通过 tcgetattr 和 tcsetattr 来获取/设置 termios 结构。
使用这些接口的时候,很容易忘记把模式重置为标准模式,从而导致终端的使用出现问题,输入下面的命令解决:
$ stty sane
Note
或者直接重启终端,把之前的设置丢弃掉就行了。
还可以在命令提示符下设置终端的模式,即通过 stty 命令。
比如:
# 取消掉回显
$ stty -echo
终端的输出
终端的类型
“终端”可能指的是 PC 上运行的一个终端仿真程序或者窗口环境中的一个终端应用程序。
终端几乎都使用 escape 转义序列来控制光标的位置和其他属性,比如黑体和闪烁等。这些序列有许多标准。
使用 terminfo 软件包统一了使用接口。它被继承在 curses 软件包中。使用它们需要引入 curses.h 和 term.h ,并加入 -lncurses 连接选项。
识别终端类型
环境变量 TERM 被设置为当前正在使用的终端类型。
terminfo 软件包包含一个由大量不同类型终端的功能标志和 escape 转义序列等信息构成的数据库,并且为使用它们提供了一个统一的编程接口。
每个 terminfo 定义由3种类型的数据项组成,每个数据项被称为 capname ,它们分别用于定义终端的一种功能标志。
-
布尔功能标志指出终端是否支持某个特定的功能。
-
数值功能标志定义长度。比如 lines 定义屏幕可以显示的行数, cols 定义的是屏幕可以显示的列数。
-
字符串功能更复杂。
使用 terminfo 功能标志
使用 terminfo 时,第一件事情就是调用 setupterm 来设置终端类型。
之后就可以查看当前终端的功能标志并使用它们的功能了。
通过 tigetflag tigetnum tigetstr 来查询终端的功能标志的值(布尔,数值,字符串)。
某些功能标志还需要参数,那么就要用到 tparm 函数生成转义序列。
接着,使用 putp 或者 tputs 函数将功能标志的值(或转义序列)发送给终端,从而可以完成诸如跳转光标这样的功能。
虚拟控制台
Linux 提供了虚拟控制台的功能,一组终端设备共享 PC 电脑的屏幕、键盘和鼠标,它们通过字符设备文件 /dev/ttyN
使用。N从1开始。
如果使用字符界面登陆 Linux 系统,这就是第一个虚拟控制台,即终端设备 /dev/tty1
。
使用 CTRL + ALT + F1 ~ F12 来切换到一个虚拟控制台。
使用 who 命令可以查询目前进系统的用户以及用的是何种终端。